package com.g0dkar.leet.util.reflection;

import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

public class MethodNamesCollector implements ClassVisitor {

    private List<String> methods = new LinkedList<String>();

    public void visit(int arg0, int arg1, String arg2, String arg3, String arg4, String[] arg5) {
    }

    public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
        return null;
    }

    public void visitAttribute(Attribute arg0) {
    }

    public void visitEnd() {
    }

    public FieldVisitor visitField(int arg0, String name, String arg2, String arg3, Object arg4) {
        return null;
    }

    public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) {
    }

    public MethodVisitor visitMethod(int arg0, String name, String signature, String arg3, String[] arg4) {
        // Evitar alguns métodos como <init> e um outro que começa com $ que
        // apareceu quando foi usado o plugin de cobertura de testes.
    	
//        if (!name.startsWith("<") && !name.startsWith("$")) {
//            TraceSignatureVisitor v =
//                    new TraceSignatureVisitor(0);
//            SignatureReader r = new SignatureReader(signature);
//            r.accept(v);
//
//            String[] types = getTypes(v.getDeclaration());
//
//            StringBuilder typesParsed = new StringBuilder();
//            for (String type : types) {
//                typesParsed.append(getClassForType(type));
//                typesParsed.append(",");
//            }
//            if (typesParsed.length() > 0) {
//                typesParsed.deleteCharAt(typesParsed.length() - 1);
//            }
//
//            methods.add(name + "-" + typesParsed.toString());
//        }
        return null;
    }

    public void visitOuterClass(String arg0, String arg1, String arg2) {
    }

    public void visitSource(String arg0, String arg1) {
    }

    public List<String> getMethodNames() {
        return methods;
    }

    /*
     * Used for remove parenteses and generate an array splitting the string by comma.
     */
    private String[] getTypes(String str) {
        str = str.replace("(", "").replace(")", "");
        if (str.length() > 0) {
            return str.split(",");
        } else {
            return new String[0];
        }
    }

    private String getClassForType(String type) {
        type = type.trim();
        Map<String, String> classes = new LinkedHashMap<String, String>();
        classes.put("char", "java.lang.Character");
        classes.put("int", "java.lang.Integer");
        classes.put("long", "java.lang.Long");
        classes.put("boolean", "java.lang.Boolean");
        classes.put("byte", "java.lang.Byte");
        classes.put("float", "java.lang.Float");
        classes.put("double", "java.lang.Double");

        if (classes.containsKey(type)) {
            return classes.get(type);
        }
        
        return type;
    }
}
